home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Celestin Apprentice 5
/
Apprentice-Release5.iso
/
Source Code
/
Libraries
/
New WASTE Handlers
/
New Sound Handler
/
WEObjectSound.c
< prev
next >
Wrap
Text File
|
1996-02-04
|
6KB
|
236 lines
// Sound Object Handler for the WASTE Text Engine
// by Michael F. Kamprath, kamprath@earthlink.net
// and Chris K. Thomas, ckt@guest.apple.com
// or thunderone@delphi.com
//
// History:
// v1.0, 16 March 1995 MFK - created
//
// v2.0b1: 11 May 1995 CKT
// almost entirely rewritten for robustness, simplicity,
// modularity and some flexibility
// v2.0b2: 2-3 June 1995 CKT
// bug fixes & now works on 68k and minor tweaking.
//
/*
Features of the new implementation:
• Single click only. The previous one wanted double
click. To the user, this is like pressing a button,
which is a single click operation.
• Improved memory management.
• Added method to stop the currently playing sound.
• Removed a bunch of unnecessary methods.
• Cleaned up the global namespace.
• Can now use any size (square) icon.
• Managed to resist the temptation to C++-ify. I
have a great stack-based SndCommand class, though...
In general, we just pollute our environment less and
manage to run faster anyway. Industrial Strength and
non-toxic.
- Chris
*/
#include <Icons.h>
#include <SoundInput.h>
#include "WASTE.h"
#include "WEObjectSound.h"
// • constants =====================================================================
#define kSoundIconID 550
#define kIconSize 16 // * change to 32 for large
// • macros ========================================================================
#define ThrowIfOSErr_(x) if(x != noErr) goto end;
// * well, okay, I couldn't help using C++ semantics, but there isn't any real C++...
// • static variables ==============================================================
static SndChannelPtr sSoundChannel = NULL;
static SndListHandle sCurrentSound = NULL;
static char sPreviousSoundState;
// • static prototypes =============================================================
static pascal OSErr HandleNewSound(Point *defaultObjectSize, WEObjectReference objectRef);
static pascal OSErr HandleDisposeSound(WEObjectReference objectRef );
static pascal Boolean HandleClickSound(Point hitPt, short modifiers,
long clickTime, WEObjectReference objectRef);
static pascal OSErr HandleDrawSound(Rect *destRect, WEObjectReference objectRef );
// • mixedmode =====================================================================
static UniversalProcPtr sNewHandlerRD = NULL;
static UniversalProcPtr sDisposeHandlerRD = NULL;
static UniversalProcPtr sDrawHandlerRD = NULL;
static UniversalProcPtr sClickHandlerRD = NULL;
// • implementation ===============================================================
// * Install the sound object handlers
// * if inChannel is NULL, we create our own.
// * if not, we use inChannel.
OSErr WEObjSoundInstall(SndChannelPtr inChannel, WEHandle inWaste)
{
OSErr theErr = noErr;
if(sNewHandlerRD == NULL)
{
sNewHandlerRD = NewWENewObjectProc(HandleNewSound);
sDisposeHandlerRD = NewWEDisposeObjectProc(HandleDisposeSound);
sDrawHandlerRD = NewWEDrawObjectProc(HandleDrawSound);
sClickHandlerRD = NewWEClickObjectProc(HandleClickSound);
}
if(inChannel == NULL)
{
theErr = SndNewChannel(&sSoundChannel, sampledSynth, 0, NULL);
ThrowIfOSErr_(theErr);
}
else
{
sSoundChannel = inChannel;
}
theErr = WEInstallObjectHandler('snd ', weNewHandler, sNewHandlerRD, inWaste);
ThrowIfOSErr_(theErr);
theErr = WEInstallObjectHandler('snd ', weDisposeHandler, sDisposeHandlerRD, inWaste);
ThrowIfOSErr_(theErr);
theErr = WEInstallObjectHandler('snd ', weDrawHandler, sDrawHandlerRD, inWaste);
ThrowIfOSErr_(theErr);
theErr = WEInstallObjectHandler('snd ', weClickHandler, sClickHandlerRD, inWaste);
ThrowIfOSErr_(theErr);
end:
return theErr;
}
// * New Object Handler for sounds
pascal OSErr HandleNewSound(Point *defaultObjectSize, WEObjectReference /*objectRef*/)
{
(*defaultObjectSize).h = kIconSize;
(*defaultObjectSize).v = kIconSize;
return noErr;
}
// * Dispose Object handler for sounds
pascal OSErr HandleDisposeSound(WEObjectReference objectRef)
{
SndListHandle theSound;
theSound = (SndListHandle)WEGetObjectDataHandle(objectRef);
if(theSound == sCurrentSound) //MFK fix
WEObjSoundStop();
DisposeHandle((Handle)theSound);
return MemError();
}
// * Draw Object handler for sounds
pascal OSErr HandleDrawSound(Rect *destRect, WEObjectReference /*objectRef*/ )
{
OSErr theErr;
theErr = PlotIconID(destRect, atNone, ttNone, kSoundIconID);
return theErr;
}
// * Click Object Handler for sounds
pascal Boolean
HandleClickSound(Point /*hitPt*/, short /*modifiers*/,
long /*clickTime*/, WEObjectReference objectRef)
{
if(sCurrentSound)
{
WEObjSoundStop();
}
sCurrentSound = (SndListHandle)WEGetObjectDataHandle( objectRef );
sPreviousSoundState = HGetState((Handle)sCurrentSound);
HLockHi((Handle)sCurrentSound);
SndPlay(sSoundChannel, sCurrentSound, true);
return true;
}
// • global sound utils ===============================================================
// * Uses built in sound recording to create a new sound object.
OSErr WEObjSoundNew( WEHandle theWE )
{
OSErr theErr;
SndListHandle sndHandle = nil;
Point corner = {kIconSize, kIconSize};
theErr = SndRecord(nil, corner, siGoodQuality, &sndHandle);
if (theErr == noErr)
{
corner.h = kIconSize;
corner.v = kIconSize;
WEInsertObject( 'snd ', (Handle)sndHandle, corner, theWE );
}
return( theErr );
}
// * idle - Call this at some point in your event loop
// * or through an idle queue etc
void WEObjSoundIdle(void)
{
if(sCurrentSound)
{
SCStatus curStatus;
SndChannelStatus(sSoundChannel, sizeof(SCStatus), &curStatus);
if(!curStatus.scChannelBusy)
HSetState((Handle)sCurrentSound, sPreviousSoundState);
}
}
// * stop the sound in progress, if any
void WEObjSoundStop(void)
{
if(sCurrentSound)
{
SCStatus curStatus;
SndChannelStatus(sSoundChannel, sizeof(SCStatus), &curStatus);
if(curStatus.scChannelBusy)
{
SndCommand ourCmd;
ourCmd.cmd = quietCmd;
ourCmd.param1 = 0;
ourCmd.param2 = 0;
(void) SndDoImmediate(sSoundChannel, &ourCmd);
HSetState((Handle)sCurrentSound, sPreviousSoundState);
// * yes, we're ignoring the error purposely
}
}
}